/*
* Copyright (c) 2025 Li Auto Inc. and its affiliates
* Licensed under the Apache License, Version 2.0(the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*	 http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <nuttx/irq.h>
#include "lnk_mpu.h"

#define REG_REGION_START      (0xF0000000UL)
#define REG_REGION_END        (0xFFFFFFFFUL)

#if defined(CONFIG_BOOT_RUNFROMFLASH)
#define MPU_CONST_ADDR_START  FLASH_CONST_START
#define MPU_CONST_ADDR_END    FLASH_CONST_END
#define MPU_TEXT_ADDR_START   FLASH_TEXT_START
#define MPU_TEXT_ADDR_END     FLASH_TEXT_END
#define MPU_IRAM_FUNC_START   FLASH_FUNC_INIT_START
#define MPU_IRAM_FUNC_END     FLASH_FUNC_INIT_END
#else
#define MPU_CONST_ADDR_START  IRAM_CONST_START
#define MPU_CONST_ADDR_END    IRAM_CONST_END
#define MPU_TEXT_ADDR_START   IRAM_TEXT_START
#define MPU_TEXT_ADDR_END     IRAM_TEXT_END
#define MPU_IRAM_FUNC_START   IRAM_FUNC_INIT_START
#define MPU_IRAM_FUNC_END     IRAM_FUNC_INIT_END
#endif

static const struct mpu_region_cfg_s core0_core_data_regions[11] = {
	{
		/* .num   = */ 0,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CRAM_TEXT_START,
		/* .limit = */ (uint32_t)CRAM_TEXT_END,
	},
	{
		/* .num   = */ 1,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_FUNC_START,
		/* .limit = */ (uint32_t)IRAM_FUNC_END,
	},
	{
		/* .num   = */ 2,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_02_NO_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_NOCACHE_START,
		/* .limit = */ (uint32_t)IRAM_NOCACHE_END,
	},
	{
		/* .num   = */ 3,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_DATA_START,
		/* .limit = */ (uint32_t)IRAM_BSS_END,
	},
	{
		/* .num   = */ 4,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_TEXT_ADDR_START,
		/* .limit = */ (uint32_t)MPU_TEXT_ADDR_END,
	},
	{
		/* .num   = */ 5,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_CONST_ADDR_START,
		/* .limit = */ (uint32_t)MPU_IRAM_FUNC_END,
	},
	{
		/* .num   = */ 6,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_03_DEVICE_NGNRNE,
		/* .base  = */ (uint32_t)REG_REGION_START,
		/* .limit = */ (uint32_t)REG_REGION_END,
	},
	{
		/* .num   = */ 7,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_LP_START,
		/* .limit = */ (uint32_t)IRAM_LP_END,
	},
	{
		/* .num   = */ 8,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)FLASH_DFLASH_START,
		/* .limit = */ (uint32_t)FLASH_DFLASH_END,
	},
	{
		/* .num   = */ 9,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_START)),
		/* .limit = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_END)),
	},
	{
		/* .num   = */ 10,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CORE0TCMC_START,
		/* .limit = */ (uint32_t)CORE0TCMC_END,
	},
};
static const struct mpu_cfg_s core0_core_mpu_cfg = {
    /* .data_region_cnt = */ 11,
    /* .data_region_cfg = */ core0_core_data_regions,
};
static const struct mpu_core_access_right_s core0_access_right = {
    /* .core_mpu_cfg = */ &core0_core_mpu_cfg,
    /* .set0_mpu_cfg = */ &empty_mpu_cfg,
};
static const struct mpu_region_cfg_s core1_core_data_regions[11] = {
	{
		/* .num   = */ 0,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CRAM_TEXT_START,
		/* .limit = */ (uint32_t)CRAM_TEXT_END,
	},
	{
		/* .num   = */ 1,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_FUNC_START,
		/* .limit = */ (uint32_t)IRAM_FUNC_END,
	},
	{
		/* .num   = */ 2,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_02_NO_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_NOCACHE_START,
		/* .limit = */ (uint32_t)IRAM_NOCACHE_END,
	},
	{
		/* .num   = */ 3,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_DATA_START,
		/* .limit = */ (uint32_t)IRAM_BSS_END,
	},
	{
		/* .num   = */ 4,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_TEXT_ADDR_START,
		/* .limit = */ (uint32_t)MPU_TEXT_ADDR_END,
	},
	{
		/* .num   = */ 5,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_CONST_ADDR_START,
		/* .limit = */ (uint32_t)MPU_IRAM_FUNC_END,
	},
	{
		/* .num   = */ 6,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_03_DEVICE_NGNRNE,
		/* .base  = */ (uint32_t)REG_REGION_START,
		/* .limit = */ (uint32_t)REG_REGION_END,
	},
	{
		/* .num   = */ 7,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_LP_START,
		/* .limit = */ (uint32_t)IRAM_LP_END,
	},
	{
		/* .num   = */ 8,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)FLASH_DFLASH_START,
		/* .limit = */ (uint32_t)FLASH_DFLASH_END,
	},
	{
		/* .num   = */ 9,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_START)),
		/* .limit = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_END)),
	},
	{
		/* .num   = */ 10,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CORE1TCMC_START,
		/* .limit = */ (uint32_t)CORE1TCMC_END,
	},
};
static const struct mpu_cfg_s core1_core_mpu_cfg = {
    /* .data_region_cnt = */ 11,
    /* .data_region_cfg = */ core1_core_data_regions,
};
static const struct mpu_core_access_right_s core1_access_right = {
    /* .core_mpu_cfg = */ &core1_core_mpu_cfg,
    /* .set0_mpu_cfg = */ &empty_mpu_cfg,
};
static const struct mpu_region_cfg_s core2_core_data_regions[11] = {
	{
		/* .num   = */ 0,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CRAM_TEXT_START,
		/* .limit = */ (uint32_t)CRAM_TEXT_END,
	},
	{
		/* .num   = */ 1,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_FUNC_START,
		/* .limit = */ (uint32_t)IRAM_FUNC_END,
	},
	{
		/* .num   = */ 2,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_02_NO_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_NOCACHE_START,
		/* .limit = */ (uint32_t)IRAM_NOCACHE_END,
	},
	{
		/* .num   = */ 3,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_DATA_START,
		/* .limit = */ (uint32_t)IRAM_BSS_END,
	},
	{
		/* .num   = */ 4,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_TEXT_ADDR_START,
		/* .limit = */ (uint32_t)MPU_TEXT_ADDR_END,
	},
	{
		/* .num   = */ 5,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_CONST_ADDR_START,
		/* .limit = */ (uint32_t)MPU_IRAM_FUNC_END,
	},
	{
		/* .num   = */ 6,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_03_DEVICE_NGNRNE,
		/* .base  = */ (uint32_t)REG_REGION_START,
		/* .limit = */ (uint32_t)REG_REGION_END,
	},
	{
		/* .num   = */ 7,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_LP_START,
		/* .limit = */ (uint32_t)IRAM_LP_END,
	},
	{
		/* .num   = */ 8,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)FLASH_DFLASH_START,
		/* .limit = */ (uint32_t)FLASH_DFLASH_END,
	},
	{
		/* .num   = */ 9,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_START)),
		/* .limit = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_END)),
	},
	{
		/* .num   = */ 10,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CORE2TCMC_START,
		/* .limit = */ (uint32_t)CORE2TCMC_END,
	},
};
static const struct mpu_cfg_s core2_core_mpu_cfg = {
    /* .data_region_cnt = */ 11,
    /* .data_region_cfg = */ core2_core_data_regions,
};
static const struct mpu_core_access_right_s core2_access_right = {
    /* .core_mpu_cfg = */ &core2_core_mpu_cfg,
    /* .set0_mpu_cfg = */ &empty_mpu_cfg,
};
static const struct mpu_region_cfg_s core3_core_data_regions[11] = {
	{
		/* .num   = */ 0,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CRAM_TEXT_START,
		/* .limit = */ (uint32_t)CRAM_TEXT_END,
	},
	{
		/* .num   = */ 1,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_FUNC_START,
		/* .limit = */ (uint32_t)IRAM_FUNC_END,
	},
	{
		/* .num   = */ 2,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_02_NO_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_NOCACHE_START,
		/* .limit = */ (uint32_t)IRAM_NOCACHE_END,
	},
	{
		/* .num   = */ 3,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_DATA_START,
		/* .limit = */ (uint32_t)IRAM_BSS_END,
	},
	{
		/* .num   = */ 4,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_TEXT_ADDR_START,
		/* .limit = */ (uint32_t)MPU_TEXT_ADDR_END,
	},
	{
		/* .num   = */ 5,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)MPU_CONST_ADDR_START,
		/* .limit = */ (uint32_t)MPU_IRAM_FUNC_END,
	},
	{
		/* .num   = */ 6,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_03_DEVICE_NGNRNE,
		/* .base  = */ (uint32_t)REG_REGION_START,
		/* .limit = */ (uint32_t)REG_REGION_END,
	},
	{
		/* .num   = */ 7,
		/* .attr  = */ USER_RX_SUPERVISOR_RX,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)IRAM_LP_START,
		/* .limit = */ (uint32_t)IRAM_LP_END,
	},
	{
		/* .num   = */ 8,
		/* .attr  = */ USER_R_SUPERVISOR_R,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)FLASH_DFLASH_START,
		/* .limit = */ (uint32_t)FLASH_DFLASH_END,
	},
	{
		/* .num   = */ 9,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_START)),
		/* .limit = */ (uint32_t)(MPU_F_TO_M_ADDR(FLASH_DFLASH_END)),
	},
	{
		/* .num   = */ 10,
		/* .attr  = */ USER_RW_SUPERVISOR_RW,
		/* .mem_attr_idx  = */ MEMATTR_TYPE_01_WRITE_THROUGH_CACHEABLE,
		/* .base  = */ (uint32_t)CORE3TCMC_START,
		/* .limit = */ (uint32_t)CORE3TCMC_END,
	},
};
static const struct mpu_cfg_s core3_core_mpu_cfg = {
	/* .data_region_cnt = */ 11,
	/* .data_region_cfg = */ core3_core_data_regions,
};
static const struct mpu_core_access_right_s core3_access_right = {
	/* .core_mpu_cfg = */ &core3_core_mpu_cfg,
	/* .set0_mpu_cfg = */ &empty_mpu_cfg,
};
const struct mpu_core_access_right_s *const os_core_access_right_ref_table[] = {
	&core0_access_right,
	&core1_access_right,
	&core2_access_right,
	&core3_access_right,
};